Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merging [time.zone], [time.clock], and [time.parse] pieces of P0355R7 #1789

Merged
merged 24 commits into from
Apr 6, 2021

Conversation

mnatsuhara
Copy link
Contributor

@mnatsuhara mnatsuhara commented Mar 30, 2021

⌚ ⌛ 🗺️

Partially addresses #12

This merges feature/chrono into main as [time.zone], [time.clock], and [time.parse] have been implemented, leaving no partially-finished pieces except for formatting (see Extensions to <chrono>).

Thanks to @d-winsor, @MattStephanson, and @StephanTLavavej for all of their hard work!

StephanTLavavej and others added 9 commits March 4, 2021 15:25
feature/chrono: Merge toolset update
* [time.clocks] C++20 clocks

* concepts workarounds for /BE

* test failures and review feedback

* buildfix

* fix _HAS_CXX20/namespace nesting

* _File_time_clock to filesystem namespace

* [time.clock.file] tests now pass, consolidate testing code

* revert whitespace change; more review feedback

* utc_clock::to_sys with floating point durations

* Unicode Windows API functions

* YOU get constexpr, YOU get constexpr, EVERYBODY gets constexpr

* Comment cleanup

* SHOUTY comments: in for a penny, in for a pound

* formatting

* static_assert wording

* improved exception handling

* switch negated test

* less macro-y alias

* explicit return types to match Standard

* renames and noexcept

* misc review feedback

* clang-format

* addressing review comments on test coverage

Co-authored-by: Miya Natsuhara <[email protected]>
* Loading time_zone names from icu.dll

* formatting

* Addressed feedback and fixed tests.

* Removed manual link map and altered tests.

* 121 chars in test script hacks :(

* Try again with tests

* Test should run now

* I think my previous changes got flagged?

* Trying to get output from tests.

* Win10 20H2 VMSS.

* Reverted CI test hacks

* Feedback and error handling.

* Version, error handling and feedback

* More feedback

* Remove qualifiers from test

Co-authored-by: mnatsuhara <[email protected]>

Co-authored-by: Stephan T. Lavavej <[email protected]>
Co-authored-by: mnatsuhara <[email protected]>
* Initial draft

* Addressed feedback

* Final feedback
Co-authored-by: Stephan T. Lavavej <[email protected]>
@mnatsuhara mnatsuhara requested a review from a team as a code owner March 30, 2021 00:28
@mnatsuhara mnatsuhara added chrono C++20 chrono cxx20 C++20 feature labels Mar 30, 2021
@StephanTLavavej StephanTLavavej changed the title Merging [time.zone] and [time.clock] pieces of P0355R7 Merging [time.zone], [time.clock], and [time.parse] pieces of P0355R7 Mar 30, 2021
@StephanTLavavej StephanTLavavej self-assigned this Mar 30, 2021
Copy link
Member

@StephanTLavavej StephanTLavavej left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just noticed some memory leaks and minor nitpicks. I'll push fixes.

stl/src/tzdb.cpp Outdated Show resolved Hide resolved
stl/src/tzdb.cpp Outdated Show resolved Hide resolved
stl/src/tzdb.cpp Outdated Show resolved Hide resolved
stl/inc/chrono Outdated Show resolved Hide resolved
stl/inc/chrono Outdated Show resolved Hide resolved
stl/inc/chrono Outdated Show resolved Hide resolved
@StephanTLavavej
Copy link
Member

I pushed the following changes:

  • stl/msbuild: Link advapi32.lib.
    • This is for the kernel32 and netfx flavors only (netfx is the special copy for the CLR). For the app and onecore flavors, onecore.lib provides the registry APIs.
  • static_cast from int to bool to avoid warning C4800.
  • Add run_tz_test() to report exceptions and handle old OSes.
    • This adds detailed reporting of system_error::code() if something fails in the future.
    • For MSVC_INTERNAL_TESTING only, where the test machines are running Server 2019 (and older!), we detect ERROR_MOD_NOT_FOUND and skip the test. Any other errors are reported (so if/when the internal machines are updated, this will begin providing real coverage). For GitHub (CI and local development), loading icu.dll is not allowed to fail.
  • Remove _Invalid_time_string to fix the internal objsize test.
    • @MattStephanson confirmed that this was no longer used (it was a relic of development). P0355R7_calendars_and_time_zones_io/test.cpp just needs a bogus value, the specific string is unimportant.
  • Work around VSO-1303556, an is_constructible_v ICE. (Which appears to be an assertion in the internal "chk" builds of the compiler, that doesn't lead to crashes in the public "ret" builds, otherwise we would have seen this earlier.)
    • Fully reduced and reported (this is a problem in the type traits optimizer which is why ::value appears to be a reliable workaround). The "circular" constraint of having zoned_time constructors query the constructibility of zoned_time is unusual, but doesn't appear to be wrong.
  • Fix memory leaks.
    • We no longer null out _Info's data members, as we delete _Info itself.
  • Code review feedback.
    • Remove extra space in comment.
    • Consistently _CHRONO qualify "near-shadowing".
    • Remove now() strengthening; utc_clock::now() isn't strengthened.
    • Cite WP number.

@StephanTLavavej StephanTLavavej removed their assignment Mar 31, 2021
@CaseyCarter CaseyCarter self-assigned this Mar 31, 2021
Copy link
Contributor

@miscco miscco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My hat is for for that incredible work. I will happily remember to not do any chrono related stuff.

I found some nits. Generally I really prefer to delete special members rather than defaulting the other ones.

stl/inc/chrono Show resolved Hide resolved
stl/inc/chrono Show resolved Hide resolved
stl/inc/chrono Outdated Show resolved Hide resolved
stl/inc/chrono Show resolved Hide resolved
stl/inc/chrono Show resolved Hide resolved
stl/inc/chrono Outdated Show resolved Hide resolved
stl/inc/chrono Show resolved Hide resolved
stl/inc/chrono Show resolved Hide resolved
stl/inc/chrono Show resolved Hide resolved
stl/inc/chrono Show resolved Hide resolved
@mnatsuhara

This comment has been minimized.

stl/inc/chrono Outdated Show resolved Hide resolved
stl/inc/chrono Outdated Show resolved Hide resolved
Co-authored-by: MattStephanson <[email protected]>
stl/inc/chrono Show resolved Hide resolved
@mnatsuhara

This comment has been minimized.

@azure-pipelines

This comment has been minimized.

Copy link
Member

@CaseyCarter CaseyCarter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of these comments relates to correctness. I'm fine with making changes now or filing a followup issue "Address Casey's comments on GH-1789," so I'm approving.

void deallocate(_Ty* const _Ptr, size_t) noexcept {
__std_free_crt(_Ptr);
}
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm disturbed by having a _Meow_allocator type in product code that doesn't satisfy the allocator requirements. It might be overkill to actually implement template <class _Ty1, class _Ty2> bool operator==(const _Crt_allocator<_Ty1>&, const _Crt_allocator<_Ty2>&), however - could we at least have a comment to the effect that this isn't really an allocator because == is missing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to have a properly implemented == (as product code should hold itself to a high standard), even though we aren't actually using it yet.

// CLASS time_zone
class time_zone {
public:
explicit time_zone(string_view _Name_) : _Name(_Name_) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make this constructor which never emits exceptions noexcept? (Note that this wouldn't be a strengthening since this constructor is unspecified.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Speaking of unspecified, should this constructor (and all similar unspecified constructors for other types) have a first parameter with an internal type so users cannot accidentally (or intentionally) construct one from a string_view?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for both. Upon looking at this again, the potential for users to write time_zone tz{"PDT"}; is dangerously high.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon looking at this again, the potential for users to write time_zone tz{"PDT"}; is dangerously high.

Yes, it would be nice to make it easier for users to avoid accidentally (or intentionally) using a non-portable initialization.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that the data member we're constructing is string _Name;, so noexcept would be unwise here.

stl/inc/chrono Show resolved Hide resolved
// CLASS time_zone_link
class time_zone_link {
public:
explicit time_zone_link(string_view _Name_, string_view _Target_) : _Name(_Name_), _Target(_Target_) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto "Should we noexcept?"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto nope, we're constructing string _Name; and string _Target;.

We can tag this constructor, though.

_Xruntime_error("Internal error loading IANA database information");
}

return {_Info->_Tz_name};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this usage is correct, brace-init of a type with an initializer_list constructor (or a type that potentially has such a constructor) when we don't intend to invoke that initializer_list constructor is a code smell. Could we just return _Info->_Tz_name; here so every future reader doesn't have to verify that this is ok?


template <class _DurationType>
_NODISCARD bool _Make_time_point(_DurationType& _Dur, _LeapSecondRep _Leap) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

if (_Leap != _LeapSecondRep::_None) {
if (_Hour_24 == 23 && _Minute == 59 && _Second >= 59) {
// It's possible that the parsed time doesn't exist because (a) _Seconds == 60 and there *isn't* a
// leap second insertion or (b) _Seconds == 59 and there *is* a leap second subtraction.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 4133 refers to negative leap second "deletion"; we should consistently use the same term throughout this file. I have no strong feelings, but note that "deletion" is more obviously an antonym of "insertion".

_NODISCARD _InIt _Parse_time_field(_InIt _First, ios_base& _Iosbase, ios_base::iostate& _State,
const char _Flag, const char _Modifier, const unsigned int _Width,
const unsigned int _Subsecond_precision) {
using _CharT = typename _InIt::value_type;
Copy link
Member

@CaseyCarter CaseyCarter Apr 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct if _InIt is a generic input iterator. It should use iterator_traits to retrieve the corresponding value type, or better yet the shortcut alias _Iter_value_t<_InIt>. If it's not a generic input iterator, we should change the name to avoid our convention that _InIt means "input iterator." It looks like these only need to work with istream_iterators; If that's the case, just plain _Iter will work. (Several occurrences.)


const auto& _Ctype_fac = _STD use_facet<ctype<_CharT>>(_Iosbase.getloc());
const auto& _Time_fac = _STD use_facet<time_get<_CharT>>(_Iosbase.getloc());
constexpr _InIt _Last{};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cpp17InputIterator does not require default construction - let alone constexpr default construction - so this is plain wrong if _InIt is meant to be a generic input iterator.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's always an istreambuf_iterator; I'll make the code accordingly specific so this will be obviously correct.

stl/inc/chrono Show resolved Hide resolved
@StephanTLavavej
Copy link
Member

Thanks @mnatsuhara, @d-winsor, and @MattStephanson for these major pieces of <chrono>! ⏳ 🎉 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chrono C++20 chrono cxx20 C++20 feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants